package com.luo.d3s.ec.infrastructure.database;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.luo.d3s.ec.domain.goods.model.Goods;
import com.luo.d3s.ec.domain.goods.model.GoodsStatus;
import com.luo.d3s.ec.domain.goods.repository.GoodsRepository;
import com.luo.d3s.ec.infrastructure.database.convertor.GoodsConvertor;
import com.luo.d3s.ec.infrastructure.database.dao.GoodsMapper;
import com.luo.d3s.ec.infrastructure.database.dao.GoodsTagBindingMapper;
import com.luo.d3s.ec.infrastructure.database.dataobject.GoodsDo;
import com.luo.d3s.ec.infrastructure.database.dataobject.GoodsTagBindingDo;
import com.luo.d3s.share.model.BizId;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品仓库实现类
 *
 * @author luohq
 * @date 2023-01-05 15:06
 */
@Repository
public class GoodsRepositoryImpl implements GoodsRepository {

    private GoodsMapper goodsMapper;

    private GoodsTagBindingMapper goodsTagBindingMapper;

    public GoodsRepositoryImpl(GoodsMapper goodsMapper, GoodsTagBindingMapper goodsTagBindingMapper) {
        this.goodsMapper = goodsMapper;
        this.goodsTagBindingMapper = goodsTagBindingMapper;
    }

    @Override
    public Goods save(Goods goods) {
        //转换商品数据对象
        GoodsDo goodsDo = GoodsConvertor.toGoodsDo(goods);
        //ID存在，则修改
        Boolean existGoods = this.existGoodsId(goods.getId());
        if (existGoods) {
            this.goodsMapper.updateById(goodsDo);
        } else {
            //ID不存在，则新增
            this.goodsMapper.insert(goodsDo);
        }

        //删除原绑定关系
        this.goodsTagBindingMapper.deleteByGoodsIds(Collections.singletonList(goodsDo.getId()));
        //批量保存新的绑定关系
        Set<Long> tagIds = Collections.emptySet();
        if (Objects.nonNull(goods.getTagIds()) && !goods.getTagIds().isEmpty()) {
            tagIds = goods.getTagIds().stream().map(BizId::getValue).collect(Collectors.toSet());
            tagIds.stream()
                    .map(tagId -> new GoodsTagBindingDo(goodsDo.getId(), tagId))
                    .forEach(goodsTagBindingMapper::insert);
        }

        //返回商品实体信息
        return GoodsConvertor.toGoods(goodsDo, tagIds);
    }

    @Override
    public Goods findById(BizId bizId) {
        //查询商品信息
        GoodsDo goodsDo = this.goodsMapper.selectById(bizId.getValue());
        if (null == goodsDo) {
            return null;
        }

        //查询商品绑定的标签
        Set<Long> tagIds = this.goodsTagBindingMapper.findTagIdsOfGoods(bizId.getValue());

        //转换商品实体
        return GoodsConvertor.toGoods(goodsDo, tagIds);
    }

    @Override
    public void removeById(BizId bizId) {
        this.deleteByIds(Collections.singletonList(bizId));
    }

    @Override
    public Boolean existGoodsInCategories(List<BizId> categoryIds) {
        //验证分类ID集合是否存在商品
        Boolean exists = this.goodsMapper.exists(Wrappers.<GoodsDo>lambdaQuery()
                .in(GoodsDo::getCategoryId, BizId.toValues(categoryIds))
        );
        return exists;
    }

    @Override
    public Boolean existGoodsShelved(List<BizId> goodsIds) {
        //验证是否存在上架状态的商品
        return this.goodsMapper.exists(Wrappers.<GoodsDo>lambdaQuery()
                .in(GoodsDo::getId, BizId.toValues(goodsIds))
                .eq(GoodsDo::getGoodsStatus, GoodsStatus.SHELVED.getValue())
        );
    }

    @Override
    public Boolean existGoodsId(BizId goodsId) {
        //验证是否存在商品
        return this.goodsMapper.exists(Wrappers.<GoodsDo>lambdaQuery()
                .eq(GoodsDo::getId, goodsId.getValue()));
    }

    /**
     * 标签下是否存在商品
     *
     * @param tagIds 标签ID列表
     * @return 是否存在
     */
    @Override
    public Boolean existsByTagIds(Collection<BizId> tagIds) {
        return goodsTagBindingMapper.existByTagIds(BizId.toValues(tagIds));
    }


    @Override
    public void deleteByIds(List<BizId> goodsIds) {
        //批量删除商品
        this.goodsMapper.deleteBatchIds(BizId.toValues(goodsIds));
        //批量删除商品标签绑定信息
        this.goodsTagBindingMapper.deleteByGoodsIds(BizId.toValues(goodsIds));
    }

    @Override
    public void batchModifyGoodsStatus(List<BizId> goodsIds, GoodsStatus goodsStatus) {
        this.goodsMapper.update(null, Wrappers.<GoodsDo>lambdaUpdate()
                .set(GoodsDo::getGoodsStatus, goodsStatus.getValue())
                .in(GoodsDo::getId, BizId.toValues(goodsIds))
        );
    }
}
